/**
* Created by chenly on 12/29/23.
* Description
**/


#ifndef SIMNOW_TEST_MDSPIIMPL_H
#define SIMNOW_TEST_MDSPIIMPL_H
//c++ headers
#include <iostream>
#include <unordered_map>
#include <cstring>
#include <fstream>
#include <memory>
#include <thread>
#include <csignal>
#include <vector>
#include <string>
#include <unordered_map>
#include <list>
#include <mutex>
#include <condition_variable>
#include <map>
//ctp headers
#include "ThostFtdcMdApi.h"
#include "ThostFtdcTraderApi.h"
#include "ThostFtdcUserApiStruct.h"
#include "MdDataQueue.h"
#include "Msg.h"

namespace lyctp {
    using namespace std;

    class MdSpiImpl final : public CThostFtdcMdSpi {

        CThostFtdcMdApi *m_md_user_api;            // 行情指针

        TThostFtdcBrokerIDType m_broker_id;         // 模拟经纪商代码
        TThostFtdcInvestorIDType m_invester_id;     // 投资者账户名
        TThostFtdcPasswordType m_invester_password; // 投资者密码
        char **m_instrument_id = nullptr;                  // 行情合约代码列表，中、上、大、郑交易所各选一种
        int m_instrument_num = 0;                        // 行情合约订阅数量
        map<string,CThostFtdcDepthMarketDataField> m_current_md_cache;
        CircleBuffer* m_circle_buffer;
    public:
        MdSpiImpl(const string& broker_id, const string& invester_id,
                  const string& invester_password) {
            strcpy(m_broker_id, broker_id.data());
            strcpy(m_invester_id, invester_id.data());
            strcpy(m_invester_password, invester_password.data());
            m_circle_buffer = new CircleBuffer(1024 * 1024 * 5, "md_buffer");
        }
        ~MdSpiImpl(){
            m_md_user_api->Release();
        }

        CircleBuffer* get_circle_buffer(){
            return m_circle_buffer;
        }
        map<string,CThostFtdcDepthMarketDataField>& get_cache(){
            return m_current_md_cache;
        }
        void set_subscribe_info(char **instrument_id, int instrument_num) {
            m_instrument_id = instrument_id;
            m_instrument_num = instrument_num;
        }
        bool connect(const string& md_front_addr){
            m_md_user_api= CThostFtdcMdApi::CreateFtdcMdApi();   // 创建行情实例
            m_md_user_api->RegisterSpi(this);               // 注册事件类
            m_md_user_api->RegisterFront(const_cast<char*>(md_front_addr.data()));           // 设置行情前置地址
            m_md_user_api->Init();
        }

        ///当客户端与交易后台建立起通信连接时（还未登录前），该方法被调用。
        void OnFrontConnected();

        ///当客户端与交易后台通信连接断开时，该方法被调用。当发生这个情况后，API会自动重新连接，客户端可不做处理。
        ///@param nReason 错误原因
        ///        0x1001 网络读失败
        ///        0x1002 网络写失败
        ///        0x2001 接收心跳超时
        ///        0x2002 发送心跳失败
        ///        0x2003 收到错误报文
        void OnFrontDisconnected(int nReason);

        ///心跳超时警告。当长时间未收到报文时，该方法被调用。
        ///@param nTimeLapse 距离上次接收报文的时间
        void OnHeartBeatWarning(int nTimeLapse);

        ///登录请求响应
        void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID,
                            bool bIsLast);

        ///登出请求响应
        void OnRspUserLogout(CThostFtdcUserLogoutField *pUserLogout, CThostFtdcRspInfoField *pRspInfo, int nRequestID,
                             bool bIsLast);

        ///错误应答
        void OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);

        ///订阅行情应答
        void OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo,
                                int nRequestID, bool bIsLast);

        ///取消订阅行情应答
        void OnRspUnSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo,
                                  int nRequestID, bool bIsLast);

        ///订阅询价应答
        void OnRspSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo,
                                 int nRequestID, bool bIsLast);

        ///取消订阅询价应答
        void OnRspUnSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo,
                                   int nRequestID, bool bIsLast);

        ///深度行情通知
        void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData);

        ///询价通知
        void OnRtnForQuoteRsp(CThostFtdcForQuoteRspField *pForQuoteRsp);
    };

}

#endif //SIMNOW_TEST_MDSPIIMPL_H
